package com.abc.bt.common.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.ReturningWork;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ClassUtils;

public class GenericDaoHibernateSupport<T> implements GenericDao<T> {
	
	@Autowired
	private SessionFactory sessionFactory;
	
	/** 当前Dao所要操作的Bean的class地址. */
	private Class<T> persistentClass;
	public GenericDaoHibernateSupport() {
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		persistentClass = (Class) pt.getActualTypeArguments()[0];
	}

	public GenericDaoHibernateSupport(final Class<T> persistentClass) {
		this.persistentClass = persistentClass;
	}
	
	protected Session getSession(){
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 删除一个Bean对象.
	 * 
	 * @param o
	 *            实体对象
	 */
	public void delete(T o) {
		this.getSession().delete(o);

	}

	/**
	 * 删除一个集合内的所有对象
	 * 
	 * @param list
	 *            对象集合
	 */
	public void deleteAll(Collection<T> list) {
		
		for(T t:list){
			this.getSession().delete(t);
		}
	}

	/**
	 * 依靠id删除一个实体对象.
	 * 
	 * @param id
	 *            实体对象的id
	 */
	public void deleteById(String id) {
		T o = this.findById(id);
		if (null == o) {
			throw new HibernateException("This Object by id is " + id
					+ " does not exist");
		}
		this.getSession().delete(o);
	}

	/**
	 * 执行SQL语句获得Set结果,此SQL语句非HQL语句.
	 * 
	 * @param sql
	 *            基本sql语句
	 * 
	 * @return Set集合
	 */
	@SuppressWarnings("deprecation")
	public ResultSet executeQuery(final String sql) throws Exception {
		ResultSet rs = null;
		try {
			
			return this.getSession().doReturningWork(new ReturningWork<ResultSet>(){
				public ResultSet execute(Connection connection) throws SQLException{
					PreparedStatement pstmt=connection.prepareStatement(sql);
					return pstmt.executeQuery();
				}
			});
		} catch (Exception e) {
			throw new Exception(this.getClass() + " execute " + sql + " ERROR!");
		}
	}

	/**
	 * 查询所有信息.
	 * 
	 * @return 实体Bean List
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		return this.getSession().createQuery("FROM "+ ClassUtils.getShortName(persistentClass)).list();
	}

	/**
	 * 根据某些属性条件查询.
	 * 
	 * @param map
	 *            存放属性name-value 相对应的条件集.
	 * @return 根据条件获得的所有数据集
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAllByProperties(Map<String, Object> map) {
		String hql = "from " + ClassUtils.getShortName(persistentClass)
				+ " where 1=1 ";
		String[] names = new String[map.size()];
		Object[] values = new Object[map.size()];
		int i = 0;
		for (String str : map.keySet()) {
			hql = hql + " and " + str + "=:" + str;
			names[i] = str;
			values[i] = map.get(str);
			i++;
		}
		Query query =this.getSession().createQuery(hql);
		
		for(int j=0;i<names.length;i++){
			query.setParameter(names[i], values[i]);
		}
		return query.list();
	}

	/**
	 * 根据属性名值进行查询.
	 * 
	 * @param propertyName
	 *            属性名字：如id，username。。。
	 * @param propertyValue
	 *            属性值： 如11，'admin'。。。
	 * @return 根据条件获得的所有数据集
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAllByProperty(final String propertyName,
			Object propertyValue) {

		String hql = "from " + ClassUtils.getShortName(persistentClass)
				+ " where " + propertyName + "= :" + propertyName;
		return this.getSession().createQuery(hql).setParameter(propertyName, propertyValue).list();
	}

	/**
	 * 依靠当前实体的id查找该实体.
	 * 
	 * @param idValue
	 *            主键值
	 * @return 该id实体对象
	 */
	public T findById(Serializable idValue) {
		return (T) this.getSession().get(persistentClass,idValue);
	}

	/**
	 * 根据属性名值进行查询.
	 * 
	 * @param propertyName
	 *            属性名字：如id，username。。。
	 * @param propertyValue
	 *            属性值： 如11，'admin'。。。
	 * @return 获得符合条件的数据的条数
	 */
	public int findColumnCount(String propertyName, Object propertyValue) {
		return this.findAllByProperty(propertyName, propertyValue).size();
	}

	
	/**
	 * 新增一条信息.
	 * 
	 */
	public void save(T value) {
		this.getSession().save(value);
	}

	/**
	 * 保存一组对象集合.
	 * 
	 * @param coll
	 *            对象集合
	 * 
	 */
	public void saveAll(Collection<T> coll) {
		for(T t:coll){
			this.getSession().save(t);
		}
	}

	/**
	 * 修改一条信息.
	 */
	public void update(T value) {
		this.getSession().update(value);
	}


	public List<T> findByHQL(String hql) {
	
		return this.getSession().createQuery(hql).list();
	}


	public void saveOrUpdate(T o) {
		
		this.getSession().saveOrUpdate(o);
	}
}
